import axios from 'axios'
import {MessageBox, Message, Loading} from 'element-ui'
import store from '@/store'
import {getRefreshToken, getToken, setToken} from '@/utils/auth'

import errorCode from '@/utils/errorCode'
import {blobValidate, tansParams} from '@/utils/ruoyi'
import {saveAs} from 'file-saver'
import {isRefreshRequest, refreshToken} from "@/api/refreshToken";
import da from "element-ui/src/locale/lang/da";
import {reLogin} from "@/api/login";

import {signUtil, aesUtil, rsaUtil, servePublicKey, privateKey} from '@/utils/encrypt'
import {getRsaKeys, rsaEncrypt, rsaDecrypt, aesDecrypt, aesEncrypt, get32RandomNum, get16RandomNum} from '@/utils/pwd'

// create an axios instance
// 这里返回的是一个promise对象
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  withCredentials: true, // send cookies when cross-domain requests
  timeout: 50000 // request timeout
})

let frontPrivateKey

// request interceptor
service.interceptors.request.use(
  async config => {
    // do something before request is sent

    let token = getToken()
    if (token && !isRefreshRequest(config)) {
      // let each request carry token
      // ['X-Token'] is a custom headers key
      // please modify it according to the actual situation
      config.headers['Authorization'] = token
    }

    if (config.method === 'post' || config.method === 'put') {
      const {privateKey, publicKey} = await getRsaKeys()
      let afterPublicKey = sessionStorage.getItem('afterPublicKey')
      frontPrivateKey = privateKey
      //每次请求生成aeskey
      let aesKey = get16RandomNum()
      //用登陆后后端生成并返回给前端的的RSA密钥对的公钥将AES16位密钥进行加密
      let aesKeyByRsa = rsaEncrypt(aesKey, afterPublicKey)
      //使用AES16位的密钥将请求报文加密（使用的是加密前的aes密钥）
      if (config.data) {
        let data = aesEncrypt(aesKey, JSON.stringify(config.data))
        config.data = {
          data: data,
          aesKey: aesKeyByRsa,
          frontPublicKey: publicKey
        }
      }
    }

    // if (config.data) {
    //   // 生成签名
    //   const signKey = signUtil.sortObjFunc(config.data)
    //   const newSignKey = rsaUtil.ensign(signKey, privateKey)
    //   // AES随机秘钥
    //   const romkey = aesUtil.genKey()
    //   // 服务端公钥对随机秘加密
    //   const aesKey = rsaUtil.encrypt(romkey, servePublicKey)
    //   // AES + 随机秘对data体加密
    //   const aesData = aesUtil.encrypt(config.data, romkey)
    //   const newData = {data: aesData, key: aesKey}
    //   config.data = newData
    //   config.data['sign'] = newSignKey
    // }

    return config
  },
  error => {
    // do something with request error
    console.log(error) // for debug
    return Promise.reject(error)
  }
)

// response interceptor
service.interceptors.response.use(
  /**
   * If you want to get http information such as headers or status
   * Please return  response => response
   */

  /**
   * Determine the request status by custom code
   * Here is just an example
   * You can also judge the status by HTTP Status Code
   */
  async (response) => {
    const data = response.data
    // if the custom code is not 20000, it is judged as an error.
    if (data.status !== 200) {
      // Message({
      //   message: data.msg || 'Error',
      //   type: 'error',
      //   duration: 5 * 1000
      // })

      //Illegal token; Other clients logged in; Token expired;
      if (data.status === 401 || data.status === 403 && !isRefreshRequest(response.config)) {
        console.log("是否触发刷新token,getRefreshToken()", JSON.stringify(getRefreshToken()))
        //判断是否有刷新token
        if (getRefreshToken()) {
          console.log("开始续期")
          const refreshResult = await refreshToken();
          console.log("refreshResult：", refreshResult)
          if (refreshResult.status === 200) {
            //更新token
            setToken(refreshResult.body.access_token, refreshResult.body.refresh_token);
            // 有新的token后，重新请求
            console.log('业务接口-重新请求');
            response.config.headers.Authorization = `Bearer ${getToken()}`;
            //重置baseURL
            response.config.baseURL = "";
            const resp = await service.request(response.config);
            return resp;
          } else {
            reLogin()
            return Promise.reject(new Error(data.msg || 'Error'))
          }
        } else {
          reLogin()
          return Promise.reject(new Error(data.msg || 'Error'))
        }
      } else if (data.status === 401 || data.status === 403 && isRefreshRequest(response.config)) {
        return data;
      }
      //return Promise.reject(new Error(data.msg || 'Error'))
    } else {
      return data
    }
  },
  error => {
    console.log('err' + error) // for debug
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    //return Promise.reject(error)
  }
)


let downloadLoadingInstance

// 通用下载方法
export function download(url, params, filename, config) {
  downloadLoadingInstance = Loading.service({
    text: '正在下载数据，请稍候',
    spinner: 'el-icon-loading',
    background: 'rgba(0, 0, 0, 0.7)'
  })
  return service.post(url, params, {
    transformRequest: [(params) => {
      return tansParams(params)
    }],
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    responseType: 'blob',
    ...config
  }).then(async (data) => {
    const isBlob = blobValidate(data)
    if (isBlob) {
      const blob = new Blob([data])
      saveAs(blob, filename)
    } else {
      const resText = await data.text()
      const rspObj = JSON.parse(resText)
      const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
      Message.error(errMsg)
    }
    downloadLoadingInstance.close()
  }).catch((r) => {
    console.error(r)
    Message.error('下载文件出现错误，请联系管理员！')
    downloadLoadingInstance.close()
  })
}

export default service
